/*
Copyright © 2021 NAME HERE <EMAIL ADDRESS>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd

import (
	"fmt"
	"gitee.com/maomaomaoge/go-utils/buff"
	"github.com/spf13/cobra"
	"io"
	"log"
	"net"
	"os"
	"strings"
	"time"
)

// keepClientCmd represents the keepClient command
var keepClientCmd = &cobra.Command{
	Use:   "keepClient [addr]",
	Short: "tcp长连接的内网接收",
	Long: `tcp长连接的内网接收`,
	Run: func(cmd *cobra.Command, args []string) {
		if len(args) == 0 {
			log.Println("少port参数")
			return
		}

		keepClient(args[0])
	},
}

func init() {
	rootCmd.AddCommand(keepClientCmd)
}

func keepClient(port string)  {
	localAddress, _ := net.ResolveTCPAddr("tcp4", port) //定义一个本机IP和端口。
	conn, err := net.DialTCP("tcp", nil,localAddress)
	if err != nil {
		log.Println(err)
		return
	}
	conn.SetKeepAlive(true)

	for {
		now := time.Now()
		// 第一次读取消息字节数
		data := make([]byte, 4)
		_, err = conn.Read(data)
		if err != nil {
			log.Println(err)
			continue
		}
		buf := buff.NewBufferBytes(data)
		allDataLen := buf.Int()
		fmt.Println("总大小:/mb ", float64(allDataLen) / 1024 / 1024)

		// 第一次读取文件名的字节数
		data = make([]byte, 4)
		_, err = conn.Read(data)
		if err != nil {
			log.Println(err)
			continue
		}
		buf = buff.NewBufferBytes(data)
		fileNameByte := buf.Int()

		// 解析文件名字
		data = make([]byte, fileNameByte)
		_, err = conn.Read(data)
		if err != nil {
			log.Println(err)
			continue
		}
		fileNameSlice := strings.Split(strings.ReplaceAll(string(data),`\`, `/`) , `/`)
		fileName := fileNameSlice[len(fileNameSlice) - 1]
		fmt.Println("解析的文件名字为: ", fileName)

		os.RemoveAll(strings.TrimSpace(fileName))
		os.Create(strings.TrimSpace(fileName))
		f, err := os.OpenFile(strings.TrimSpace(fileName), os.O_WRONLY|os.O_CREATE|os.O_APPEND, os.ModePerm)
		if err != nil {
			fmt.Println("????")
			log.Println(err)
			continue
		}

		var curByte int
		for {
			// todo: 可以尝试每一次大点字节的读取
			tmpData := make([]byte, 1024 * 1024 * 5)
			read, err := conn.Read(tmpData)
			if err != nil || err == io.EOF {
				break
			}

			f.Write(tmpData[:read])
			f.Seek(1, read)
			curByte += read
			fmt.Println("当前进度:% ", float64(curByte) / float64(allDataLen) * 100)

			if curByte == allDataLen {
				break
			}
		}

		fmt.Println("上传完成")
		f.Sync() // 强制刷盘
		f.Close()

		fmt.Println("文件总大小:/mb ", float64(allDataLen) / 1024 / 1024)
		fmt.Println("总用时: ", time.Since(now).String())

		fmt.Println("平均速度:/mb/s ", float64(allDataLen) / 1024 / 1024 / time.Since(now).Seconds())
	}
}